package edu.tsinghua.ddb.util;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class MultiThreadWaiter<V> {
	private List<Callable<V>> requests;

	private List<V> responses;

	private boolean closed = false;

	private Throwable throwable;

	public MultiThreadWaiter() {
		requests = new LinkedList<Callable<V>>();
		responses = new LinkedList<V>();
	}

	public void add(Callable<V> c) {
		assert !closed;
		requests.add(c);
	}

	// if any exception, as no response
	public void executeAll() {
		closed = true;
		ExecutorService es = Executors.newFixedThreadPool(requests.size());
		List<Future<V>> results = null;
		try {
			results = es.invokeAll(requests);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		for (Future<V> result : results) {
			assert result.isDone();
			try {
				V v = result.get();
				responses.add(v);
			} catch (ExecutionException e) {
				throwable = e.getCause();
			} catch (InterruptedException e) {
			}
		}
		es.shutdown();
	}

	public List<V> getResultList(boolean isCompletenessRequired)
			throws Exception {
		assert closed;
		if (isCompletenessRequired && requests.size() != responses.size())
			throw new Exception(throwable);
		return responses;
	}
}
